﻿//**********************************************************
//Copyright(C)2010 By 波特商网公司 版权所有。
//
//文件名：
//文件功能：数字输入TextBox自定义控件
//
//创建标识：陈博生 || 2011-06-02
//
//修改标识：
//修改描述：
//**********************************************************

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Hmc.IM.Common.UserControls;
using System.Windows.Forms;

namespace Hmc.IM.Common.UserControls
{
    /// <summary>
    /// 数字输入TextBox自定义控件
    /// </summary>
    public partial class ucTextNumber : ucTextBox
    {
        #region 自定义属性

        /// <summary>
        /// 输入字符消息（键盘输入的，输入法输入的好像不是这个消息） 
        /// </summary>
        private const int WM_CHAR = 0x0102;

        /// <summary>
        /// 程序发送此消息给editcontrol或combobox从剪贴板中得到数据 
        /// </summary>
        private const int WM_PASTE = 0x0302;
 
        #region 小数位精确位数
        private int _decimalPlaces = 0;

        /// <summary>
        /// 小数位精确位数
        /// </summary>
        [Browsable(true)]
        [Category("Data")]
        [Description("指示要显示的小数位数")]
        [DefaultValue(0)]
        public int DecimalPlaces
        {
            get
            { return _decimalPlaces; }
            set
            {
                if (value < 0)
                {
                    MessageBox.Show("无效的值！小数位数只能为（0-28）", "验证错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    _decimalPlaces = 0;
                }
                else if (value > 28)
                {
                    MessageBox.Show("无效的值！小数位数只能为（0-28）", "验证错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    _decimalPlaces = 28;
                }
                else
                {
                    _decimalPlaces = value;
                }


            }
        }
        #endregion

        #region 允许输入的上限
        private decimal _maximum = 999999999999999;
        /// <summary>
        /// 允许输入的上限
        /// </summary>
        [Category("Data")]
        [Browsable(true)]
        [Description("允许输入的上限")]
        [DefaultValue(999999999999999)]
        public decimal Maximum
        {
            get { return _maximum; }
            set
            {
                if (Minimum > value)
                {
                    MessageBox.Show("最小值不能大于最大值", "验证错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    _minimum = 0;
                    return;
                }
                if (value > 999999999999999)
                {
                    MessageBox.Show("最大值不能超过999999999999999", "验证错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    _maximum = 999999999999999;
                }
                else
                {
                    _maximum = decimal.Round(value, DecimalPlaces);
                    string strText = base.Text;
                    if (!CheckMaxMin(ref strText))
                    {
                        base.Text = strText;
                    }

                }

            }
        }
        #endregion

        #region 允许输入的下限
        private decimal _minimum = 0;
        /// <summary>
        /// 允许输入的下限
        /// </summary>
        [Category("Data")]
        [Browsable(true)]
        [Description("允许输入的下限")]
        [DefaultValue(0)]
        public decimal Minimum
        {
            get { return _minimum; }
            set
            {
         
                if (value > Maximum)
                {
                    MessageBox.Show("最小值不能大于最大值", "验证错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    _minimum = 0;
                    return;
                }
                // update end  by 2010-06-10
                if (value < -999999999999999)
                {
                    MessageBox.Show("最小值不能小于-999999999999999", "验证错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    _minimum = -999999999999999;
                    return;
                }
                else
                {
                    _minimum = decimal.Round(value, DecimalPlaces);
                    string strText = base.Text;
                    if (!CheckMaxMin(ref strText))
                    {
                        base.Text = strText;
                    }
                }
            }
        }
        #endregion

        #region 是否显示千分符
        private bool _thousandsSeparator = false;
        /// <summary>
        /// 是否显示千分符
        /// </summary>
        [Browsable(true)]
        [Category("Data")]
        [Description("指示是否在每三位十进制数之间插入千位分隔符")]
        [DefaultValue(false)]
        public bool ThousandsSeparator
        {
            get { return _thousandsSeparator; }
            set { _thousandsSeparator = value; }
        }
        #endregion

        #region 控件内容是否为编码
        private bool _code = false;
        /// <summary>
        /// 控件内容是否为编码
        /// </summary>
        [Browsable(true)]
        [Category("Data")]
        [Description("控件内容是否为编码")]
        [DefaultValue(false)]
        public bool Code
        {
            get { return _code; }
            set { _code = value; }
        }
        #endregion

        #endregion
        /// <summary>
        /// 构造函数
        /// </summary>
        public ucTextNumber()
        {
            InitializeComponent();
        }

        #region 重写方法
        /// <summary>
        /// 消息回调处理
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_CHAR:
                    System.Console.WriteLine(m.WParam);
                    bool isSign = ((int)m.WParam == 45); // "-"键
                    bool isNum = ((int)m.WParam >= 48) && ((int)m.WParam <= 57);
                    bool isBack = (int)m.WParam == (int)Keys.Back;
                    bool isDelete = (int)m.WParam == (int)Keys.Delete;//实际上这是一个"."键 
                    bool isCtr = ((int)m.WParam == 24) || ((int)m.WParam == 22) || ((int)m.WParam == 26) || ((int)m.WParam == 3);
                    bool isDecimalPlaces = CheckDecimalPlaces();

                    if (isNum || isBack || isCtr)
                    {
                        //输入为数字并且光标在小数点前面
                        if (isNum && this.SelectionStart <= this.Text.IndexOf("."))
                        {
                            base.WndProc(ref m);
                            break;
                        }
                        //如果输入了‘-’，光标在第一位时候，不能输入
                        if (base.Text.IndexOf("-") == 0 && this.SelectionStart == 0 && !isBack) break;

                        //update start 修复复制问题 2010-06-16
                        if ((isDecimalPlaces || isBack) && !isCtr)
                        //update end 修复复制问题 2010-06-16
                        {
                            base.WndProc(ref m);
                            if (ThousandsSeparator)
                            {
                                //第一位值不是‘.’和光标不在第一位时
                                if (base.Text.IndexOf(".") == -1 && this.SelectionStart != 0)
                                {
                                    try
                                    {
                                        base.Text = string.Format("{0:N0}", decimal.Parse(base.Text));
                                        this.SelectionStart = base.Text.Length;
                                    }
                                    catch(Exception ex)
                                    {
                                        Logger.Write(ex);
                                        System.Windows.Forms.SendKeys.Send("{BACKSPACE}");
                                        break;
                                    }

                                }
                            }
                        }
                        if (isCtr)
                            base.WndProc(ref m);

                    }
                    if (isSign)
                    {
                        if (this.SelectionStart != 0 || this.Text.IndexOf("-") != -1 || _code)
                        {
                            break;
                        }
                        base.WndProc(ref m);
                        break;
                    }

                    if (isDelete)
                    {
                        //小数位数设置为0时候
                        if (DecimalPlaces == 0) break;

                        //-.不能输入
                        if (this.Text.IndexOf("-") == 0 && this.SelectionStart < 2)
                        {
                            break;
                        }
                        if (DecimalPlaces > 0)
                        {
                            int Index = this.SelectionStart;
                            //反选数字处理
                            if (!string.IsNullOrEmpty(this.SelectedText))
                            {
                                Index = Index + this.SelectionLength;
                            }
                            //例如“12345”，小数设置为2 ，不在在3前输入小数点
                            if (this.Text.Length - Index > DecimalPlaces)
                                break;
                        }
                        if (this.Text.IndexOf(".") < 0)
                        {
                            base.WndProc(ref m);
                        }
                    }

                    if ((int)m.WParam == 1)
                    {
                        this.SelectAll();
                    }
                    break;

                case WM_PASTE:
                    IDataObject iData = Clipboard.GetDataObject();//取剪贴板对象
                    if (iData.GetDataPresent(DataFormats.Text)) //判断是否是Text
                    {
                        try
                        {
                            string strTemp = iData.GetData(DataFormats.Text).ToString().Trim();//取数据
                            string strText = decimal.Parse(strTemp).ToString();
                            if (CheckClipboard(strText))
                            {
                                Clipboard.SetText(strText);
                                base.WndProc(ref m);
                                break;
                            }

                        }
                        catch (Exception ex)
                        {
                            Logger.Write(ex);
                        }
                    }

                    m.Result = (IntPtr)0;//不可以粘贴
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }

        }

        /// <summary>
        /// 最大最小值校验
        /// </summary>
        /// <param name="e"></param>
        protected override void OnValidating(CancelEventArgs e)
        {
            string strText = base.Text;
            if (!_code)
                if (!CheckMaxMin(ref strText))
                    e.Cancel = true;

            base.Text = strText;

            base.OnValidating(e);
        }

        /// <summary>
        /// 获取焦点
        /// </summary>
        /// <param name="e"></param>
        protected override void OnGotFocus(EventArgs e)
        {
            if (ThousandsSeparator)
                base.Text = ToDoubleToString(base.Text);
            base.OnGotFocus(e);
        }
        /// <summary>
        /// 失去焦点
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLostFocus(EventArgs e)
        {
            if (ThousandsSeparator)
                base.Text = ReDoubleToString(base.Text);
            base.OnLostFocus(e);
        }
        #endregion

        #region 自定义方法

        /// <summary>
        /// 剪切板内容检验
        /// </summary>
        /// <param name="ClipboardText"></param>
        /// <returns></returns>
        private bool CheckClipboard(string ClipboardText)
        {
            int index = 0;
            string strNum = "-0.123456789";

            index = ClipboardText.IndexOf(strNum[0]);
            if (index >= 0)
            {
                if (index > 0)
                {
                    return false;
                }
                index = this.SelectionStart;
                if (index > 0)
                {
                    return false;
                }
            }
            //有“.”的时候
            if (ClipboardText.IndexOf(".") != -1)
            {
                //如果小数点位数>设定小数位数
                if (ClipboardText.Substring(ClipboardText.IndexOf(".") + 1).Length > DecimalPlaces)
                    return false;
            }

            index = ClipboardText.IndexOf(strNum[2]);
            if (index != -1)
            {
                index = this.Text.IndexOf(strNum[2]);
                if (index != -1 && this.Text.Length < 0)
                {
                    return false;
                }
            }

            for (int i = 0; i < ClipboardText.Length; i++)
            {
                index = strNum.IndexOf(ClipboardText[i]);
                if (index < 0)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 检验最大值与最小值
        /// </summary>
        /// <param name="strText"></param>
        /// <returns></returns>
        private bool CheckMaxMin(ref string strText)
        {
            if (strText.IndexOf("-") != -1 && strText.Length == 1)
            {
                strText = Minimum.ToString();
                return false;
            }

            if (strText.IndexOf(".") != -1 && strText.Length == 1)
            {
                strText = Minimum.ToString();
                return false;
            }

            if (strText.Length >= 1)
            {
                try
                {
                    decimal intText = decimal.Round(decimal.Parse(strText), DecimalPlaces);

                    if (intText < Minimum)
                    {
                        strText = Minimum.ToString();
                        return false;
                    }
                    if (intText > Maximum)
                    {
                        strText = Maximum.ToString();
                        return false;
                    }
                    strText = intText.ToString();
                }
                catch(Exception ex)
                {
                    Logger.Write(ex);
                    if (strText.IndexOf("-") != 0)
                        strText = Maximum.ToString();
                    else
                        strText = Minimum.ToString();
                }
            }

            return true;
        }

        /// <summary>
        /// 键盘输入的数字小数位控制
        /// </summary>
        /// <returns>TRUE小数位符合设定值，FALSE小数位超过设定值</returns>
        private bool CheckDecimalPlaces()
        {
            int index = 0;
            if (this.SelectionStart > 0)
            {
                string strtext = base.Text;
                if (strtext.IndexOf(".") != -1)
                    index = strtext.Substring(strtext.IndexOf(".")).Length;
            }
            if (index <= DecimalPlaces || (index <= this.SelectionStart && !string.IsNullOrEmpty(this.SelectedText)))
                return true;
            else
                return false;
        }

        /// <summary>
        /// 转换为千分字符
        /// </summary>
        /// <param name="doublestring"></param>
        /// <returns></returns>
        public string ToDoubleToString(string doublestring)
        {
            string str = "";
            if (doublestring.IndexOf(',') == -1)
            {
                //查找是否带有"-"号
                int stringfu = doublestring.IndexOf('-');
                if (stringfu != -1)
                {
                    doublestring = doublestring.Replace("-", "");
                }
                //查找是否带有小数点
                int stringxiaoshu = doublestring.IndexOf('.');
                //如果不带小数点满三位就加一个千分符
                if (stringxiaoshu == -1)
                {
                    //字符串长度
                    int stringlength = doublestring.Length;
                    //大于3就加个千分符
                    if (stringlength > 3)
                    {
                        char[] charstr = doublestring.ToCharArray(0, stringlength);
                        int charstrlength = charstr.Length;
                        //反转后的字符串
                        string[] strfan = new string[charstrlength];
                        for (int i = charstrlength - 1; i >= 0; i--)
                        {
                            strfan[charstrlength - (i + 1)] = charstr[i].ToString();
                        }
                        //加上千分符
                        for (int i = 0; i < charstrlength; i++)
                        {
                            if (i != 0 && i % 3 == 0)
                            {
                                strfan[i] = strfan[i] + ",";
                            }
                        }
                        //还原顺序                    
                        for (int i = charstrlength - 1; i >= 0; i--)
                        {
                            str = str + strfan[i];
                        }
                    }
                    else
                    {
                        str = doublestring;
                    }
                }
                else
                {
                    string[] strr1 = doublestring.Split('.');
                    if (strr1[0].Length > 3)
                    {
                        int stringlength = strr1[0].Length;
                        char[] charstr = strr1[0].ToCharArray(0, stringlength);
                        int charstrlength = charstr.Length;
                        //反转后的字符串
                        string[] strfan = new string[charstrlength];
                        for (int i = charstrlength - 1; i >= 0; i--)
                        {
                            strfan[charstrlength - (i + 1)] = charstr[i].ToString();
                        }
                        //加上千分符
                        for (int i = 0; i < charstrlength; i++)
                        {
                            if (i != 0 && i % 3 == 0)
                            {
                                strfan[i] = strfan[i] + ",";
                            }
                        }
                        //还原顺序                    
                        for (int i = charstrlength - 1; i >= 0; i--)
                        {
                            str = str + strfan[i];
                        }
                        str = str + "." + strr1[1];

                    }
                    else
                    {
                        str = doublestring;
                    }
                }
                if (stringfu != -1)
                {
                    str = "-" + str;
                }
            }
            else
            {
                str = doublestring;
            }
            return str;
        }

        /// <summary>
        /// 去除千分符字符    
        /// </summary>
        /// <param name="doublestring"></param>
        /// <returns></returns>
        public string ReDoubleToString(string doublestring)
        {
            string str = doublestring;
            if (doublestring.IndexOf(',') != -1)
            {
                str = doublestring.Replace(",", "");
            }
            return str;
        }

        #endregion

    }
}
